package com.lh.disruptor;

import com.alibaba.fastjson2.JSONObject;
import com.lh.disruptor.handler.CaculateHandler;
import com.lh.disruptor.handler.ParamHandler;
import com.lh.disruptor.handler.Query1Handler;
import com.lh.disruptor.handler.Query2Handler;
import com.lmax.disruptor.BlockingWaitStrategy;
import com.lmax.disruptor.EventFactory;
import com.lmax.disruptor.EventTranslatorTwoArg;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import lombok.extern.log4j.Log4j;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.async.DeferredResult;

import javax.annotation.PostConstruct;
import java.util.concurrent.ThreadFactory;

/**
 * @author: linghao
 * @since: 2025/5/24
 */
@Slf4j
@Component
public class DisruptorServer {

    private Disruptor<Event> disruptor;
    private RingBuffer<Event> ringBuffer;
    @Autowired
    private EventTranslator eventTranslator;

    @PostConstruct
    public void init(){
        EventFactory<Event> eventFactory = EventFactorys.getEventFactory();
        ThreadFactory threadFactory = new DisruptorThreadFactory("disruptor");
        disruptor = new Disruptor<>(eventFactory,2048,threadFactory, ProducerType.MULTI,new BlockingWaitStrategy());
        initHandler();
        ringBuffer = disruptor.getRingBuffer();
        log.info("disruptor init完成");
    }

    private void initHandler(){
        ParamHandler paramHandler = new ParamHandler();
        Query1Handler query1Handler = new Query1Handler();
        Query2Handler query2Handler = new Query2Handler();
        CaculateHandler caculateHandler = new CaculateHandler();
        disruptor.handleEventsWith(paramHandler)
                .then(query1Handler,query2Handler)
                .then(caculateHandler);
    }

    //发布事件
    public void publishDeferred(JSONObject param, DeferredResult deferredResult){
        boolean b = ringBuffer.tryPublishEvent(eventTranslator, param, deferredResult);
        if(!b){
            //发布事件失败，立即返回，防止请求阻塞
            deferredResult.setResult("publishDeferred 发布失败");
        }
    }
}

@Component
class EventTranslator implements EventTranslatorTwoArg<Event, JSONObject, DeferredResult>{

    @Override
    public void translateTo(Event event, long l, JSONObject param, DeferredResult deferredResult) {
        event.setParam(param);
        event.setDeferredResult(deferredResult);
    }
}
